package engine

import (
	"github.com/kataras/golog"
	"sdn-executor/core/cli"
	model "sdn-executor/model/cli"
	"sdn-executor/model/common"
	"sdn-executor/storage/sql/executor"
	"sdn-executor/utils/erros"
)

// ExecuteCLI 执行CLI命令
func ExecuteCLI(m *Message) *model.Result {
	requestId := m.RequestId
	err := executor.UpdateSdnExecutorResultStatusByRequestIdAndOrder(requestId, 0, string(common.ExecStatusExecuting))
	if err != nil {
		return buildCLIFailResult(requestId, []*model.CommandResult{}, err)
	}

	query := m.Request.(*model.Query)
	device := query.Device

	client, err := cli.NewClient(device, query.Port, query.User, query.Password)
	if err != nil {
		golog.Errorf("cli.NewClient failed. device: %s, requestId: %s, err: %+v", device, requestId, err)
		e := executor.FailSdnExecutorResult(requestId, 0, "", err.Msg)
		if e != nil {
			golog.Errorf("sql.FailSdnExecutorResult failed. device: %s, requestId: %s, err: %+v", device, requestId, e)
		}
		return buildCLIFailResult(requestId, []*model.CommandResult{}, err)
	}
	defer client.Close()

	// 发送命令
	results, err := client.SendCommands(query, requestId, string(MsgTypeCLI))
	if err != nil {
		golog.Errorf("cli.SendCommands failed. device: %s, requestId: %s, err: %+v", device, requestId, err)
		if e := executor.FailSdnExecutorResult(requestId, 0, "", err.Msg); e != nil {
			golog.Errorf("sql.FailSdnExecutorResult failed.device: %s, requestId: %s, err: %+v", device, requestId, e)
		}
		return buildCLIFailResult(requestId, results, err)
	}

	if e := executor.SuccessSdnExecutorResult(requestId, 0, ""); e != nil {
		golog.Errorf("sql.SuccessSdnExecutorResult failed.device: %s, requestId: %s, err: %+v", device, requestId, e)
	}
	return buildCLISuccessResult(requestId, results)
}

func buildCLIFailResult(requestId string, results []*model.CommandResult, err *erros.Error) *model.Result {
	return &model.Result{
		Code:      err.Code,
		Msg:       err.Msg,
		RequestId: requestId,
		Status:    common.ExecStatusFail,
		Echos:     results,
	}
}

func buildCLISuccessResult(requestId string, results []*model.CommandResult) *model.Result {
	return &model.Result{
		Code:      erros.OK.Code,
		Msg:       erros.OK.Msg,
		RequestId: requestId,
		Status:    common.ExecStatusSuccess,
		Echos:     results,
	}
}
